
#include "analysis.h"
#include "present_blocks.h"
#include "utility.h"

#include <cmath>
#include <set>

using namespace std;
/*
set<string> permute_left(string str, const set<string> &abet)
{
    set<string> ret;
    for(set<string>::iterator iter = abet.begin() ; iter != abet.end() ; iter++)
    {
        ret.insert(*iter + str);
    }
    return ret;
}

set<string> permute_right(string str, const set<string> &abet)
{
    set<string> ret;
    for(set<string>::iterator iter = abet.begin() ; iter != abet.end() ; iter++)
    {
        ret.insert(str + *iter);
    }
    return ret;
}
*/
inline void permute(const string &str, const set<string> &abet, set<string> &left, set<string> &right)
{
    string left_str;
    string right_str;
    for(set<string>::iterator iter = abet.begin() ; iter != abet.end() ; iter++)
    {
        left_str = *iter + str;
        right_str = str + *iter;
        left.insert(left_str);
        if(left_str != right_str)
            right.insert(right_str);
    }
}

ostream& analysis::report(ostream &out)
{
    abet.report(out);
    debs.report(out);
    return out;
}

void analysis::analyse(const std::string &sequence, std::string::size_type max_length)
{
    set<string> left_perms;
    set<string> right_perms;

    debs.set_max_length(max_length);
    abet.extract_from_string(sequence);
    set<string> abet_set = abet.get_set();
    string::size_type start_from=2;
    present_blocks present_n;
    present_blocks present_n_plus_1;

    //present_n.from_sequence(sequence, 1, abet.size());
    present_n_plus_1.from_sequence(sequence,1,abet.size());

    for(string::size_type len = 1 ; len < max_length ; len++)
    {
        //cerr << "Analysing length " << len << endl;
        present_n.swap(present_n_plus_1);
        //cerr << "Present sequences of length " << len << " " << present_n.size() << endl;
        present_n_plus_1.from_sequence(sequence,len+1,pow(abet.size(), len+1));
        //cerr << "Present sequences of length " << len+1 << " " << present_n_plus_1.size() << endl;

        if(present_n_plus_1.size() == pow(abet.size(), len+1))
        {
            //cerr << "Length " << len+1 << " full, skipping permuting length " << len << endl;
            start_from = len;
        }
        else
        while(!present_n.end())// && present_n_plus_1.size() < pow(abet.size(), len+1) )
        {
            left_perms.clear();
            right_perms.clear();

            permute(present_n.current(sequence), abet_set, left_perms, right_perms);

            for(set<string>::iterator iter = left_perms.begin() ; iter != left_perms.end() ; iter++)
            {
                if(!present_n_plus_1.contains(*iter))
                {
                    debs.add_with_left_checking(*iter, start_from);
                }
            }
            for(set<string>::iterator iter = right_perms.begin() ; iter != right_perms.end() ; iter++)
            {
                if(!present_n_plus_1.contains(*iter))
                {
                    debs.add_with_right_checking(*iter, start_from);
                }
            }
            present_n.next();
        }
        //cerr << endl;
    }

}
